import { ref, watch } from 'vue'

/**
 * 数据持久化工具类
 */
export class Persistence {
  /**
   * 创建响应式持久化数据
   * @param {string} key - 存储键
   * @param {any} defaultValue - 默认值
   * @param {object} options - 配置选项
   * @returns {Ref} 响应式数据
   */
  static createPersistentRef(key, defaultValue, options = {}) {
    const {
      storage = localStorage,
      serializer = JSON,
      sync = true
    } = options

    // 从存储中读取初始值
    const getStoredValue = () => {
      try {
        const stored = storage.getItem(key)
        return stored ? serializer.parse(stored) : defaultValue
      } catch (error) {
        console.warn(`读取存储数据失败: ${key}`, error)
        return defaultValue
      }
    }

    // 创建响应式引用
    const data = ref(getStoredValue())

    // 保存到存储
    const saveToStorage = (value) => {
      try {
        if (value === null || value === undefined) {
          storage.removeItem(key)
        } else {
          storage.setItem(key, serializer.stringify(value))
        }
      } catch (error) {
        console.error(`保存数据到存储失败: ${key}`, error)
      }
    }

    // 监听数据变化并自动保存
    if (sync) {
      watch(data, saveToStorage, { deep: true })
    }

    // 手动保存方法
    data.save = () => saveToStorage(data.value)

    // 手动加载方法
    data.load = () => {
      data.value = getStoredValue()
    }

    // 清除方法
    data.clear = () => {
      data.value = defaultValue
      storage.removeItem(key)
    }

    return data
  }

  /**
   * 创建会话级持久化数据（页面刷新后清除）
   * @param {string} key - 存储键
   * @param {any} defaultValue - 默认值
   * @param {object} options - 配置选项
   * @returns {Ref} 响应式数据
   */
  static createSessionRef(key, defaultValue, options = {}) {
    return this.createPersistentRef(key, defaultValue, {
      ...options,
      storage: sessionStorage
    })
  }

  /**
   * 创建带过期时间的持久化数据
   * @param {string} key - 存储键
   * @param {any} defaultValue - 默认值
   * @param {number} ttl - 过期时间（毫秒）
   * @param {object} options - 配置选项
   * @returns {Ref} 响应式数据
   */
  static createExpiringRef(key, defaultValue, ttl, options = {}) {
    const data = this.createPersistentRef(key, defaultValue, options)
    
    // 检查是否过期
    const checkExpiry = () => {
      try {
        const stored = localStorage.getItem(`${key}_expiry`)
        if (stored) {
          const expiry = parseInt(stored)
          if (Date.now() > expiry) {
            data.clear()
            localStorage.removeItem(`${key}_expiry`)
            return true
          }
        }
      } catch (error) {
        console.warn(`检查过期时间失败: ${key}`, error)
      }
      return false
    }

    // 重写保存方法，添加过期时间
    const originalSave = data.save
    data.save = () => {
      originalSave()
      localStorage.setItem(`${key}_expiry`, (Date.now() + ttl).toString())
    }

    // 初始化时检查过期
    if (checkExpiry()) {
      data.value = defaultValue
    }

    return data
  }

  /**
   * 批量操作存储
   */
  static batch = {
    /**
     * 批量设置
     * @param {object} data - 要存储的数据对象
     * @param {object} options - 配置选项
     */
    set(data, options = {}) {
      const { storage = localStorage, serializer = JSON } = options
      
      Object.entries(data).forEach(([key, value]) => {
        try {
          storage.setItem(key, serializer.stringify(value))
        } catch (error) {
          console.error(`批量设置失败: ${key}`, error)
        }
      })
    },

    /**
     * 批量获取
     * @param {string[]} keys - 要获取的键数组
     * @param {object} options - 配置选项
     * @returns {object} 获取到的数据对象
     */
    get(keys, options = {}) {
      const { storage = localStorage, serializer = JSON } = options
      const result = {}
      
      keys.forEach(key => {
        try {
          const stored = storage.getItem(key)
          result[key] = stored ? serializer.parse(stored) : null
        } catch (error) {
          console.warn(`批量获取失败: ${key}`, error)
          result[key] = null
        }
      })
      
      return result
    },

    /**
     * 批量删除
     * @param {string[]} keys - 要删除的键数组
     * @param {object} options - 配置选项
     */
    remove(keys, options = {}) {
      const { storage = localStorage } = options
      
      keys.forEach(key => {
        try {
          storage.removeItem(key)
        } catch (error) {
          console.error(`批量删除失败: ${key}`, error)
        }
      })
    }
  }

  /**
   * 存储工具方法
   */
  static utils = {
    /**
     * 获取存储使用情况
     * @param {Storage} storage - 存储对象
     * @returns {object} 使用情况统计
     */
    getUsage(storage = localStorage) {
      let totalSize = 0
      let itemCount = 0
      
      for (let key in storage) {
        if (storage.hasOwnProperty(key)) {
          const value = storage.getItem(key)
          totalSize += key.length + (value ? value.length : 0)
          itemCount++
        }
      }
      
      return {
        totalSize,
        itemCount,
        averageSize: itemCount > 0 ? Math.round(totalSize / itemCount) : 0
      }
    },

    /**
     * 清理过期数据
     * @param {Storage} storage - 存储对象
     * @returns {number} 清理的条目数
     */
    cleanupExpired(storage = localStorage) {
      let cleanedCount = 0
      const now = Date.now()
      
      for (let key in storage) {
        if (storage.hasOwnProperty(key) && key.endsWith('_expiry')) {
          try {
            const expiry = parseInt(storage.getItem(key))
            if (now > expiry) {
              const dataKey = key.replace('_expiry', '')
              storage.removeItem(dataKey)
              storage.removeItem(key)
              cleanedCount++
            }
          } catch (error) {
            console.warn(`清理过期数据失败: ${key}`, error)
          }
        }
      }
      
      return cleanedCount
    },

    /**
     * 导出存储数据
     * @param {Storage} storage - 存储对象
     * @returns {string} JSON字符串
     */
    export(storage = localStorage) {
      const data = {}
      for (let key in storage) {
        if (storage.hasOwnProperty(key)) {
          data[key] = storage.getItem(key)
        }
      }
      return JSON.stringify(data, null, 2)
    },

    /**
     * 导入存储数据
     * @param {string} jsonData - JSON字符串
     * @param {Storage} storage - 存储对象
     * @param {boolean} clearFirst - 是否先清空现有数据
     */
    import(jsonData, storage = localStorage, clearFirst = false) {
      try {
        if (clearFirst) {
          storage.clear()
        }
        
        const data = JSON.parse(jsonData)
        Object.entries(data).forEach(([key, value]) => {
          storage.setItem(key, value)
        })
      } catch (error) {
        console.error('导入存储数据失败:', error)
        throw error
      }
    }
  }
}

// 导出便捷方法
export const createPersistentRef = Persistence.createPersistentRef
export const createSessionRef = Persistence.createSessionRef
export const createExpiringRef = Persistence.createExpiringRef
